#include "Radar.h"
#include<iostream>

using namespace std;
using namespace bfs;

Radar::Radar()
{
	m_bCreate = false;
}

int Radar::scan(string sSourceDir, bool bRecurse, bool bCreate)
{
	m_bCreate = bCreate;
	m_xCodebaseRoot = complete(path(sSourceDir, native));

	if( !exists(m_xCodebaseRoot) )
	{
		cerr<<m_xCodebaseRoot.leaf()<<" does not exist.\n";
		return 2;
	}

	if( !is_directory(m_xCodebaseRoot))
	{
		cerr<<m_xCodebaseRoot.leaf()<<" is not a directory.\n";
		return 3;
	}

	m_xNeptunerRoot = complete(path(".neptuner"),m_xCodebaseRoot);

	if(m_bCreate)
		create_directory(m_xNeptunerRoot);

	scanDirectory(m_xCodebaseRoot);

	return 0;
}

bool Radar::isFileTypeSupported(string sExtension)
{
	if(sExtension == ".c" )		return true;
	if(sExtension == ".cpp" )	return true;
	if(sExtension == ".h" )		return true;
	if(sExtension == ".hpp")	return true;

	return false;
}

bool Radar::isInIgnoreList(std::string sFileName)
{
	if(sFileName[0] == '.')		return true;
	return false;
}


string Radar::getCodeBaseLocation(bfs::path xDirEntryPath)
{
	string sSourceDirBase	=  m_xCodebaseRoot.directory_string();
	string sDirEntryPath	=  xDirEntryPath.string();

	sDirEntryPath.erase(0,sSourceDirBase.length()+1);
	//+1 since starting with / also absolute path!
	return sDirEntryPath;
}

int Radar::createShadowDirFor(path xSourceDir)
{
	string sSourceDir = xSourceDir.string();

	if(xSourceDir == m_xNeptunerRoot)
		return 1;
		//Otherwise recursive directories created if TargetDirBase is within SourceDirBase

	sSourceDir = getCodeBaseLocation(sSourceDir);
	path xShadowDir = complete(path(sSourceDir), m_xNeptunerRoot);

	if(m_bCreate)
		create_directory(xShadowDir);

	return 0;
}

void Radar::scanDirectory(const path& xPath, int nLevel, bool bRecurse)
{
	directory_iterator pxLooper(xPath); //VSExpress Intellisense has a problem with this
	directory_iterator pxLoopEnd;
	path xDirEntry;
	CodeBaseUnit* pxCodeBaseUnit = NULL;

	for(; pxLooper != pxLoopEnd; ++pxLooper)
	{
		xDirEntry = *pxLooper;

		try {
		if(isInIgnoreList(xDirEntry.filename()))
			continue;

		bool bIsDirectory = is_directory(xDirEntry);
		if(bIsDirectory)
		{
			if( 0!= createShadowDirFor(xDirEntry))
				continue;

			if(bRecurse)
				scanDirectory(xDirEntry, nLevel, bRecurse);
		}
		else
			//For files
		{
			string sFileExtension = extension(xDirEntry);
			if (!isFileTypeSupported(sFileExtension))
				continue;
		}

		pxCodeBaseUnit = new CodeBaseUnit;
		pxCodeBaseUnit->m_sName = xDirEntry.filename();
		pxCodeBaseUnit->m_sLocation = getCodeBaseLocation(xDirEntry.parent_path().string());
		pxCodeBaseUnit->m_nLevel = nLevel;
		pxCodeBaseUnit->m_eType = bIsDirectory ? CodeBaseUnit::eCBUDirectory : CodeBaseUnit::eCBUFile;

		m_xCodeBase.m_apxUnit.push_back(pxCodeBaseUnit);
		} catch(const std::exception & ex) {
			std::cerr<<pxLooper->leaf() <<": " <<ex.what() <<std::endl;
		}
	}  //End of for()
}  

void Radar::dump()
{
	int i, n= m_xCodeBase.m_apxUnit.size();
	std::string s;
	CodeBaseUnit* pxCodeBaseUnit = NULL;

	for(i=0; i< n; i++)
	{
		pxCodeBaseUnit = m_xCodeBase.m_apxUnit[i];

		cout << pxCodeBaseUnit->m_sLocation << ",";
		cout << pxCodeBaseUnit->m_sName << ",";
		cout << pxCodeBaseUnit->m_eType;

		cout<<endl;
	}
}
